const fse = require('fs-extra')
const { resolve, join } = require('path')
const UPLOAD_DIR = resolve(__dirname, '..', 'target')
const multiparty = require('multiparty')
// 文件数据库
const FileModel = require('../db/FileModel')
// 获取post数据内容
const resolvePost = async (req) =>
  new Promise(reslove => {
    let chunk = ''
    req.on('data', data => {
      chunk += data
    })
    req.on('end', _ => {
      reslove(JSON.parse(chunk))
    })
  }).catch(err => console.log(err))
// 获取文件后缀名
const extractExt = filename =>
  filename.slice(filename.lastIndexOf('.'), filename.length)

// 合并文件
const mergeFileChunk = async (filePath, filehash, size, filepath) => {
  const chunkDir = join(UPLOAD_DIR, filepath, filehash)
  const chunkPaths = await fse.readdir(chunkDir)
  chunkPaths.sort((a, b) => a.split("-")[1] - b.split("-")[1])
  // console.log(chunkPaths);
  await Promise.all(
    chunkPaths.map((chunkPath, index) =>
      pipStream(
        resolve(chunkDir, chunkPath), // 单个文件片的路径
        fse.createWriteStream(filePath, {
          start: index * size,
          end: (index + 1) * size
        }) // 创建一个可写流
      )
    )
  ).catch(err => console.log(err))
  console.log('文件合并成功');
  fse.rmdirSync(chunkDir);
}
const pipStream = (path, writeStream) =>
  new Promise(resolve => {
    const readStream = fse.createReadStream(path)
    readStream.on('end', _ => {
      fse.unlinkSync(path)
      resolve()
    })
    readStream.pipe(writeStream)
  }).catch(err => console.error(err))

module.exports = class {
  async handleVerifyUpload(req, res) {
    const { filename, filehash, filepath } = await resolvePost(req)
    // filepath 文件夹要放的位置
    console.log(filepath);
    const ext = extractExt(filename)
    // console.log(ext);
    // const filePath = resolve(UPLOAD_DIR, `${filehash}${ext}`)
    const filePath = join(UPLOAD_DIR, filepath,`${filehash}${ext}`)
    // 这里查找的是文件片合成的文件
    const chunkDir = join(UPLOAD_DIR, filepath, filehash)
    var uploadedList = [] // 已上传文件 的索引
    if (fse.existsSync(chunkDir)) {
      const uploaded = await fse.readdir(chunkDir)
      // 找到已经上传的文件
      // console.log(uploadedList);
      uploadedList = uploaded.map(chunk =>
        Number(chunk.split('-')[1])
      )
    }
    if (fse.existsSync(filePath)) {
      res.end(
        JSON.stringify({
          shouldUpload: false
        })
      )
    } else {
      res.end(
        JSON.stringify({
          shouldUpload: true,
          uploadedList
        })
      )
    }
  }
  async handleFormData(req, res) {
    const multipart = new multiparty.Form()
    multipart.parse(req, async (err, fields, files) => {
      if (err) {
        console.error(err);
        res.status = 500;
        res.end("process file chunk failed");
        return;
      }
      const [chunk] = files.chunk
      const [hash] = fields.hash;
      const [filehash] = fields.filehash;
      const [filename] = fields.filename;
      const [filepath] = fields.filepath;
      // console.log(filename,filehash);
      // 存数据库
      const isExist = await FileModel.findOne({ filehash })
      if (!isExist) {
        // await FileModel.delete({filehash})
        const model = await FileModel.create({ filename, filehash })
        console.log(model);
      }
      const filePath = join(UPLOAD_DIR, filepath,`${filehash}${extractExt(filename)}`)
      const chunkDir = join(UPLOAD_DIR, filepath, filehash) // 文件目录
      if (fse.existsSync(filePath)) {
        res.end("file exist");
        return;
      }
      if (!fse.existsSync(chunkDir)) {
        // 如果目录地址有没有 target
        await fse.mkdirs(chunkDir);
      }
      await fse.move(chunk.path, resolve(chunkDir, hash));
      res.end("received file chunk");
    })
  }
  // 文件合并
  async handleMerge(req, res) {
    const data = await resolvePost(req)
    // 拿到请求数据
    const { filehash, filename, size, filepath } = data
    const ext = extractExt(filename) // 拿到后缀名
    const filePath = join(UPLOAD_DIR, filepath, `${filehash}${ext}`)
    await mergeFileChunk(filePath, filehash, size, filepath)

    res.end(
      JSON.stringify({
        code: 0,
        message: "file merged success"
      })
    )
  }
}